#include "audio_process.h"
#include "kiss_fftr.h"
#include <stdlib.h>
#include <stdint.h>
#include "math.h"


#define EPSILON 1e-6

float * m_coefficients =  NULL;

static float *temp = NULL;

static int fft_size = 0;

kiss_fftr_cfg m_cfg;

float *m_fft_input = NULL;

float *m_energy = NULL;

kiss_fft_cpx *m_fft_output = NULL;

int m_energy_size;

int m_pooled_energy_size;

int m_windows_size;

//#define M_PI 3.1415926535897

void hammingwindow(int window_size)
{
    float float_value = 0;
     m_coefficients = malloc(sizeof(float) * window_size);
	
    // create the constants for a hamming window
    const float arg = M_PI * 2.0 / window_size;
    for (int i = 0; i < window_size; i++)
    {
        float_value = 0.5 - (0.5 * cos(arg * (i + 0.5)));
        // Scale it to fixed point and round it.
        m_coefficients[i] = float_value;
    }
   

}


void audio_process_init(int window_size)
{

    hammingwindow(window_size);
    fft_size = 1;
    while (fft_size < window_size) 
    {
        fft_size <<= 1;
    }
	m_cfg = kiss_fftr_alloc(fft_size, 0, 0, 0);
	m_fft_input = malloc(fft_size*sizeof(float));
	m_energy_size= fft_size / 2 + 1; //512/2+1
    m_fft_output = malloc(sizeof(kiss_fft_cpx) * m_energy_size);
	m_energy = malloc(sizeof(float) * m_energy_size);
    m_pooled_energy_size = ceilf((float)m_energy_size / (float)6); //43
    m_windows_size = window_size;
	for(int i =0; i < fft_size; i++)
		 m_fft_input[i] = 0;
}

void  get_spectrogram(short *data_array, float *out_buffer)
{
    int total_add = 0;
    short max = 0;

    for (int i = 0; i < m_windows_size; i++) {
          m_fft_input[i] = (float)data_array[i]/(1<<15);
         
		 //if(fabsf((float)data_array[i] - mean) > max)
		 //	max = fabsf((float)data_array[i] - mean);
      }

	
   for(int i =0; i < m_windows_size; i++)
    	{
         //  m_fft_input[i] = (float)(data_array[i] - mean)/max;
            m_fft_input[i] = (float)m_fft_input[i] * m_coefficients[i];

	    }
    for (int i = m_windows_size; i < fft_size; i++)
        {
            m_fft_input[i] = 0;
        }
     kiss_fftr(m_cfg, m_fft_input,(kiss_fft_cpx *)m_fft_output);
	 for (int i = 0; i < m_energy_size; i++)
	  {
		  const float real = m_fft_output[i].r;
		  const float imag = m_fft_output[i].i;
		  const float mag_squared = (real * real) + (imag * imag);
		  m_energy[i] = mag_squared;
	  }
    float *output_src = m_energy;
    float *output_dst = out_buffer;
	int m_pooling_size = 6;
	 for (int i = 0; i < m_energy_size; i += m_pooling_size)
    {
        float average = 0;
        for (int j = 0; j < m_pooling_size; j++)
        {
            if (i + j < m_energy_size)
            {
                average += *output_src;
                output_src++;
            }
        }
        *output_dst = average / m_pooling_size;
         output_dst++;
    }

    // now take the log to give us reasonable values to feed into the network
    for (int i = 0; i < m_pooled_energy_size; i++)
    {
        out_buffer[i] = log10f(out_buffer[i] + EPSILON);



    }

}

